{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/home/tjean/projects/dagworks/burr/.venv/bin/python: No module named pip\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "# execute this cell to install dependencies in the current environment\n",
    "# useful when using Google Colab notebooks\n",
    "%pip install sf-hamilton[visualization] requests openai lancedb burr[start,opentelemetry] pydantic pyarrow opentelemetry-instrumentation-openai opentelemetry-instrumentation-lancedb"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Use the 2-layer approach for a maintainable RAG system [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/dagworks-inc/burr/blob/main/examples/hamilton-integration/notebook.ipynb) [![GitHub badge](https://img.shields.io/badge/github-view_source-2b3137?logo=github)](https://github.com/dagworks-inc/burr/blob/main/examples/hamilton-integration/notebook.ipynb)\n",
    "\n",
    "Ready-made solutions can get you started with GenAI, but building reliable product features with retrieval augmented generation (RAG) and LLM agents inevitably required custom code. This post shares the 2-layer approach to build a maintainable RAG application that will evolve with your needs. To illustrate these ideas, we will show how a typical RAG project might evolve.\n",
    "\n",
    "The 2-layer approach is about separating the high-level logic of your application from its implementation details. In Burr, the separation is represented by the `Application` (high-level) and the `action` (low-level). Over the lifetime of your product, you will iterate on both at different times.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# execute to load the Burr and Hamilton extensions\n",
    "%load_ext burr.integrations.notebook\n",
    "%load_ext hamilton.plugins.jupyter_magic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# set your OpenAI API key\n",
    "import os\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"...\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## V1: A simple LLM pipeline\n",
    "### Layer 2: Define the `Application` logic\n",
    "\n",
    "Maybe counter-inuitively, you should start with the high-level logic, the layer 2, to determine how your application should behave. For instance:\n",
    "\n",
    "1. actions: what are the things your application can do?\n",
    "2. transitions & conditions: when should an action be performed?\n",
    "3. inputs, results, & state: what data is required to execute an action or to decide which action to perform?\n",
    "\n",
    "Skipping these initial questions usually leads to refactoring and slows down development.\n",
    "\n",
    "In the next snippet, we build a simple application that ingests a blog post and allows to ask questions over its content. We outline our application logic without writing the body of the `@action` functions (level 2) and build it with the `ApplicationBuilder` to view the graph."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"303pt\" height=\"177pt\"\n",
       " viewBox=\"0.00 0.00 303.00 177.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 173)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-173 299,-173 299,4 -4,4\"/>\n",
       "<!-- ingest_blog -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>ingest_blog</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M254,-103C254,-103 176,-103 176,-103 170,-103 164,-97 164,-91 164,-91 164,-78 164,-78 164,-72 170,-66 176,-66 176,-66 254,-66 254,-66 260,-66 266,-72 266,-78 266,-78 266,-91 266,-91 266,-97 260,-103 254,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ingest_blog</text>\n",
       "</g>\n",
       "<!-- ask_question -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>ask_question</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M188.5,-37C188.5,-37 99.5,-37 99.5,-37 93.5,-37 87.5,-31 87.5,-25 87.5,-25 87.5,-12 87.5,-12 87.5,-6 93.5,0 99.5,0 99.5,0 188.5,0 188.5,0 194.5,0 200.5,-6 200.5,-12 200.5,-12 200.5,-25 200.5,-25 200.5,-31 194.5,-37 188.5,-37\"/>\n",
       "<text text-anchor=\"middle\" x=\"144\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ask_question</text>\n",
       "</g>\n",
       "<!-- ingest_blog&#45;&gt;ask_question -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>ingest_blog&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M195.22,-65.67C187.84,-59.01 179.31,-51.33 171.36,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"173.44,-41.33 163.67,-37.23 168.76,-46.53 173.44,-41.33\"/>\n",
       "</g>\n",
       "<!-- input__blog_post_url -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>input__blog_post_url</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"295,-169 135,-169 135,-132 295,-132 295,-169\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-146.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: blog_post_url</text>\n",
       "</g>\n",
       "<!-- input__blog_post_url&#45;&gt;ingest_blog -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>input__blog_post_url&#45;&gt;ingest_blog</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M215,-131.67C215,-125.99 215,-119.55 215,-113.33\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"218.5,-113.23 215,-103.23 211.5,-113.23 218.5,-113.23\"/>\n",
       "</g>\n",
       "<!-- input__user_query -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>input__user_query</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"146,-103 0,-103 0,-66 146,-66 146,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"73\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: user_query</text>\n",
       "</g>\n",
       "<!-- input__user_query&#45;&gt;ask_question -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>input__user_query&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M92.78,-65.67C100.16,-59.01 108.69,-51.33 116.64,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"119.24,-46.53 124.33,-37.23 114.56,-41.33 119.24,-46.53\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<burr.core.application.Application at 0x7f3a33ed4190>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from burr.core import action, State, ApplicationBuilder\n",
    "\n",
    "# `reads` and `writes` specify what data is read/written via the `State`.\n",
    "@action(reads=[], writes=[\"blog_content\"])\n",
    "def ingest_blog(state: State, blog_post_url: str) -> State:\n",
    "    \"\"\"Download a blog post and parse it\"\"\"\n",
    "    blog_content = ...\n",
    "    return state.update(blog_content=blog_content)\n",
    "\n",
    "\n",
    "@action(reads=[\"blog_content\", \"history\"], writes=[\"history\"])\n",
    "def ask_question(state: State, user_query: str) -> State:\n",
    "    \"\"\"Reply to the user's query using the blog's content.\"\"\"\n",
    "    history = state[\"history\"]\n",
    "    blog_content = state[\"blog_content\"]\n",
    "    response = ...\n",
    "    return state.append(history=response)\n",
    "\n",
    "\n",
    "# the `ApplicationBuilder` receives the actions,\n",
    "# specifies the transitions, and sets the starting action.\n",
    "(\n",
    "    ApplicationBuilder()\n",
    "    .with_actions(ingest_blog, ask_question)\n",
    "    .with_transitions((\"ingest_blog\", \"ask_question\"))\n",
    "    .with_entrypoint(\"ingest_blog\")\n",
    "    .build()\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This outline sets \"contracts\" for the role and input/output of each actions. As you implement individual actions, you might decide to merge/split actions, modify state variables, etc. Then, you can revisit and update your application outline."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Layer 1: Implement individual `@action`\n",
    "\n",
    "At the start of our project, with might come up with this simple `Application`:\n",
    "1. `ingest_blog` downloads an HTML page, parses it into a plain text.\n",
    "2. `ask_question` prompts an OpenAI LLM with the full blog in the prompt and the user query.\n",
    "\n",
    "By using \"plain\" Python libraries instead of LLM frameworks, it will be easier to find bugs and modify our code as our application needs evolve."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import openai\n",
    "from bs4 import BeautifulSoup\n",
    "from burr.core import action, State, ApplicationBuilder\n",
    "\n",
    "\n",
    "@action(reads=[], writes=[\"blog_content\"])\n",
    "def ingest_blog_v1(state: State, blog_post_url: str) -> State:\n",
    "    \"\"\"Download a blog post and parse it\"\"\"\n",
    "    html_content = requests.get(blog_post_url).text\n",
    "    soup = BeautifulSoup(html_content, \"html.parser\")\n",
    "    blog_content = soup.get_text(separator=\" \", strip=True)\n",
    "    return state.update(blog_content=blog_content)\n",
    "\n",
    "\n",
    "@action(reads=[\"blog_content\"], writes=[\"llm_answer\"])\n",
    "def ask_question_v1(state: State, user_query: str) -> State:\n",
    "    \"\"\"Reply to the user's query using the blog's content.\"\"\"\n",
    "    blog_content = state[\"blog_content\"]\n",
    "\n",
    "    system_prompt = (\n",
    "        \"Answer the user's questions based on the provided blog post content. \"\n",
    "        \"Answer in a concise and helpful manner, and tell the user \"\n",
    "        \"if you don't know the answer or you're unsure.\\n\\n\"\n",
    "        f\"BLOG CONTENT:\\n{blog_content}\"\n",
    "    )\n",
    "\n",
    "    client = openai.OpenAI()\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"gpt-4o-mini\",\n",
    "        messages=[\n",
    "            {\"role\": \"system\", \"content\": system_prompt},\n",
    "            {\"role\": \"user\", \"content\": user_query}\n",
    "        ],\n",
    "    )\n",
    "    llm_answer = response.choices[0].message.content\n",
    "    return state.update(llm_answer=llm_answer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"303pt\" height=\"177pt\"\n",
       " viewBox=\"0.00 0.00 303.00 177.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 173)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-173 299,-173 299,4 -4,4\"/>\n",
       "<!-- ingest_blog -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>ingest_blog</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M254,-103C254,-103 176,-103 176,-103 170,-103 164,-97 164,-91 164,-91 164,-78 164,-78 164,-72 170,-66 176,-66 176,-66 254,-66 254,-66 260,-66 266,-72 266,-78 266,-78 266,-91 266,-91 266,-97 260,-103 254,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ingest_blog</text>\n",
       "</g>\n",
       "<!-- ask_question -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>ask_question</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M188.5,-37C188.5,-37 99.5,-37 99.5,-37 93.5,-37 87.5,-31 87.5,-25 87.5,-25 87.5,-12 87.5,-12 87.5,-6 93.5,0 99.5,0 99.5,0 188.5,0 188.5,0 194.5,0 200.5,-6 200.5,-12 200.5,-12 200.5,-25 200.5,-25 200.5,-31 194.5,-37 188.5,-37\"/>\n",
       "<text text-anchor=\"middle\" x=\"144\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ask_question</text>\n",
       "</g>\n",
       "<!-- ingest_blog&#45;&gt;ask_question -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>ingest_blog&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M195.22,-65.67C187.84,-59.01 179.31,-51.33 171.36,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"173.44,-41.33 163.67,-37.23 168.76,-46.53 173.44,-41.33\"/>\n",
       "</g>\n",
       "<!-- input__blog_post_url -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>input__blog_post_url</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"295,-169 135,-169 135,-132 295,-132 295,-169\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-146.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: blog_post_url</text>\n",
       "</g>\n",
       "<!-- input__blog_post_url&#45;&gt;ingest_blog -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>input__blog_post_url&#45;&gt;ingest_blog</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M215,-131.67C215,-125.99 215,-119.55 215,-113.33\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"218.5,-113.23 215,-103.23 211.5,-113.23 218.5,-113.23\"/>\n",
       "</g>\n",
       "<!-- input__user_query -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>input__user_query</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"146,-103 0,-103 0,-66 146,-66 146,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"73\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: user_query</text>\n",
       "</g>\n",
       "<!-- input__user_query&#45;&gt;ask_question -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>input__user_query&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M92.78,-65.67C100.16,-59.01 108.69,-51.33 116.64,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"119.24,-46.53 124.33,-37.23 114.56,-41.33 119.24,-46.53\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<burr.core.application.Application at 0x7f3a34013a10>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app_v1 = (\n",
    "    ApplicationBuilder()\n",
    "    .with_actions(ingest_blog=ingest_blog_v1, ask_question=ask_question_v1)\n",
    "    .with_transitions((\"ingest_blog\", \"ask_question\"))\n",
    "    .with_entrypoint(\"ingest_blog\")\n",
    "    .build()\n",
    ")\n",
    "app_v1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In a RAG application, you need to monitor:\n",
      "\n",
      "1. **User Behavior Patterns** - Analyze frequent topics and difficult queries.\n",
      "2. **Application Performance** - Track aspects like guardrails, LLM randomness, and user ratings.\n",
      "3. **System Performance** - Measure latency, throughput, resource usage, and API calls.\n",
      "4. **System Errors** - Identify bugs in the code or interactions between code and data.\n",
      "\n",
      "Using tools like OpenTelemetry can help gather and export this telemetry data effectively.\n"
     ]
    }
   ],
   "source": [
    "action_name, results, state = app_v1.run(\n",
    "    halt_after=[\"ask_question\"],\n",
    "    inputs={\n",
    "        \"blog_post_url\": \"https://blog.dagworks.io/p/from-blog-to-bot-build-a-rag-app\",\n",
    "        \"user_query\": \"What do you need to monitor in a RAG app?\"\n",
    "    }\n",
    ")\n",
    "print(state[\"llm_answer\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## V2: Let's use RAG\n",
    "\n",
    "While `V1` simply ingested the blog and prompted the LLM, `V2` will add RAG capabilities.\n",
    "\n",
    "We have to ask ourselves: are we making changes to layer 1 or 2? For now, we'll focus on modifying the actions (layer 1) rather than the application logic (layer 2)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Layer 1: Adding RAG\n",
    "In the next snippet, you'll notice:\n",
    "- we define a `TextDocument` model to create the schema of our LanceDB table. It specifies to embed the `text` field using the OpenAI model.\n",
    "- because text chunks are stored on disk, we don't need to pass them via the `Application` state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/tjean/projects/dagworks/burr/.venv/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    }
   ],
   "source": [
    "import re\n",
    "import requests\n",
    "import openai\n",
    "import lancedb\n",
    "from bs4 import BeautifulSoup\n",
    "from burr.core import action, State, ApplicationBuilder\n",
    "from lancedb.pydantic import LanceModel, Vector\n",
    "from lancedb.embeddings import get_registry\n",
    "\n",
    "\n",
    "embedding_model = get_registry().get(\"openai\").create()\n",
    "\n",
    "class TextDocument(LanceModel):\n",
    "    \"\"\"Simple data structure to hold a piece of text associated with a url.\"\"\"\n",
    "    url: str\n",
    "    position: int\n",
    "    text: str = embedding_model.SourceField()\n",
    "    vector: Vector(dim=embedding_model.ndims()) = embedding_model.VectorField()\n",
    "\n",
    "\n",
    "@action(reads=[], writes=[])\n",
    "def ingest_blog_v2(state: State, blog_post_url: str) -> State:\n",
    "    \"\"\"Download a blog post and parse it\"\"\"\n",
    "    # get the blog post as plain text\n",
    "    html_content = requests.get(blog_post_url).text\n",
    "    soup = BeautifulSoup(html_content, \"html.parser\")\n",
    "    blog_content = soup.get_text(separator=\" \", strip=True)\n",
    "    # split the text by sentence\n",
    "    SENTENCE_ENDINGS = r\"[.!?]+\"\n",
    "\n",
    "    chunks = []\n",
    "    for sentence in re.split(SENTENCE_ENDINGS, blog_content):\n",
    "        sentence = sentence.strip()\n",
    "        if sentence:\n",
    "            chunks.append(sentence)\n",
    "\n",
    "    # join sentences to create larger overlapping chunks\n",
    "    window = 5\n",
    "    stride = 3\n",
    "    min_window_size = 2\n",
    "\n",
    "    overlapping_chunks = []\n",
    "    n_chunks = len(chunks)\n",
    "    for start_i in range(0, n_chunks, stride):\n",
    "        if (start_i + window <= n_chunks) or (n_chunks - start_i >= min_window_size):\n",
    "            overlapping_chunks.append(\" \".join(chunks[start_i : min(start_i + window, n_chunks)]))\n",
    "\n",
    "    # embed and store the chunks using LanceDB\n",
    "    con = lancedb.connect(\"./blogs\")\n",
    "    table = con.create_table(\"chunks\", exist_ok=True, schema=TextDocument)\n",
    "    table.add([\n",
    "        {\"text\": c, \"url\": blog_post_url, \"position\": i}\n",
    "        for i, c in enumerate(overlapping_chunks)\n",
    "    ])\n",
    "            \n",
    "    return state\n",
    "\n",
    "\n",
    "@action(reads=[], writes=[\"llm_answer\"])\n",
    "def ask_question_v2(state: State, user_query: str) -> State:\n",
    "    \"\"\"Reply to the user's query using the blog's content.\"\"\"\n",
    "    # retrieve the most relevant chunks\n",
    "    chunks_table = lancedb.connect(\"./blogs\").open_table(\"chunks\")\n",
    "    search_results = (\n",
    "        chunks_table\n",
    "        .search(user_query)\n",
    "        .select([\"text\", \"url\", \"position\"])\n",
    "        .limit(3)\n",
    "        .to_list()\n",
    "    )\n",
    "    relevant_content = \"\\n\".join([r[\"text\"] for r in search_results])\n",
    "\n",
    "    # prompt the LLM with the relevant content\n",
    "    system_prompt = (\n",
    "        \"Answer the user's questions based on the provided blog post content. \"\n",
    "        f\"BLOG CONTENT:\\n{relevant_content}\"\n",
    "    )\n",
    "\n",
    "    client = openai.OpenAI()\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"gpt-4o-mini\",\n",
    "        messages=[\n",
    "            {\"role\": \"system\", \"content\": system_prompt},\n",
    "            {\"role\": \"user\", \"content\": user_query}\n",
    "        ],\n",
    "    )\n",
    "    llm_answer = response.choices[0].message.content\n",
    "    return state.update(llm_answer=llm_answer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Layer 2: Tracking and observing your application\n",
    "\n",
    "A keep requirement to improve your application is being able to observe and track its behavior. Burr makes it simple to add a tracker to your application, which is compatible with OpenTelemetry.\n",
    "\n",
    "> NOTE. Some lines are commented out because OpenTelemetry doesn't work properly in notebooks. See `application.py` for an example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"303pt\" height=\"177pt\"\n",
       " viewBox=\"0.00 0.00 303.00 177.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 173)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-173 299,-173 299,4 -4,4\"/>\n",
       "<!-- ingest_blog -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>ingest_blog</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M254,-103C254,-103 176,-103 176,-103 170,-103 164,-97 164,-91 164,-91 164,-78 164,-78 164,-72 170,-66 176,-66 176,-66 254,-66 254,-66 260,-66 266,-72 266,-78 266,-78 266,-91 266,-91 266,-97 260,-103 254,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ingest_blog</text>\n",
       "</g>\n",
       "<!-- ask_question -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>ask_question</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M188.5,-37C188.5,-37 99.5,-37 99.5,-37 93.5,-37 87.5,-31 87.5,-25 87.5,-25 87.5,-12 87.5,-12 87.5,-6 93.5,0 99.5,0 99.5,0 188.5,0 188.5,0 194.5,0 200.5,-6 200.5,-12 200.5,-12 200.5,-25 200.5,-25 200.5,-31 194.5,-37 188.5,-37\"/>\n",
       "<text text-anchor=\"middle\" x=\"144\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ask_question</text>\n",
       "</g>\n",
       "<!-- ingest_blog&#45;&gt;ask_question -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>ingest_blog&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M195.22,-65.67C187.84,-59.01 179.31,-51.33 171.36,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"173.44,-41.33 163.67,-37.23 168.76,-46.53 173.44,-41.33\"/>\n",
       "</g>\n",
       "<!-- input__blog_post_url -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>input__blog_post_url</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"295,-169 135,-169 135,-132 295,-132 295,-169\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-146.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: blog_post_url</text>\n",
       "</g>\n",
       "<!-- input__blog_post_url&#45;&gt;ingest_blog -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>input__blog_post_url&#45;&gt;ingest_blog</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M215,-131.67C215,-125.99 215,-119.55 215,-113.33\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"218.5,-113.23 215,-103.23 211.5,-113.23 218.5,-113.23\"/>\n",
       "</g>\n",
       "<!-- input__user_query -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>input__user_query</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"146,-103 0,-103 0,-66 146,-66 146,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"73\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: user_query</text>\n",
       "</g>\n",
       "<!-- input__user_query&#45;&gt;ask_question -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>input__user_query&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M92.78,-65.67C100.16,-59.01 108.69,-51.33 116.64,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"119.24,-46.53 124.33,-37.23 114.56,-41.33 119.24,-46.53\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<burr.core.application.Application at 0x7f3a3018c4d0>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# \"instrumenting\" patches the libraries to log OpenTelemetry data\n",
    "# from opentelemetry.instrumentation.lancedb import LanceInstrumentor\n",
    "# from opentelemetry.instrumentation.openai import OpenAIInstrumentor\n",
    "\n",
    "# OpenAIInstrumentor().instrument()\n",
    "# LanceInstrumentor().instrument()\n",
    "\n",
    "app_v2 = (\n",
    "    ApplicationBuilder()\n",
    "    .with_actions(ingest_blog=ingest_blog_v2, ask_question=ask_question_v2)\n",
    "    .with_transitions((\"ingest_blog\", \"ask_question\"))\n",
    "    .with_entrypoint(\"ingest_blog\")\n",
    "    # enable the tracker and enable OpenTelemetry via the argument\n",
    "    .with_tracker(project=\"modular-rag\", use_otel_tracing=True)\n",
    "    .build()\n",
    ")\n",
    "app_v2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In a RAG application, you need to monitor the following aspects:\n",
      "\n",
      "1. **User Behavior Patterns**: This includes frequent topics and difficult queries that users engage with.\n",
      "2. **Application Performance**: You should track metrics such as guardrails, LLM randomness, and user ratings.\n",
      "3. **System Performance**: Monitor system metrics like latency, throughput, resource usage, and API calls.\n",
      "4. **System Errors**: Keep an eye on bugs that may arise from code or the interaction between code and data.\n"
     ]
    }
   ],
   "source": [
    "action_name, results, state = app_v2.run(\n",
    "    halt_after=[\"ask_question\"],\n",
    "    inputs={\n",
    "        \"blog_post_url\": \"https://blog.dagworks.io/p/from-blog-to-bot-build-a-rag-app\",\n",
    "        \"user_query\": \"What do you need to monitor in a RAG app?\"\n",
    "    }\n",
    ")\n",
    "print(state[\"llm_answer\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Burr UI: http://127.0.0.1:7241\n"
     ]
    }
   ],
   "source": [
    "# execute cell to launch the UI\n",
    "%burr_ui"
   ]
  },
  {
   "attachments": {
    "image.png": {
     "image/png": "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"
    }
   },
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By navigating to the `modular-rag` project, you can see logged runs. With OpenTelemetry support, we can inspect the LanceDB operations and the OpenAI calls. For instance, this allows us to see which were the relevant chunks retrieved and passed to the LLM.\n",
    "\n",
    "![image.png](burr_ui_app_v2.png)\n",
    "\n",
    "The Burr UI has other useful features:\n",
    "- view token usage\n",
    "- annotate state values and logged attributes\n",
    "- create test fixtures from application state\n",
    "- and more "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## V3: Keeping your code modular\n",
    "\n",
    "You probably noticed that actions functions in `V2` started to be long and do several things. It would be a good time to refactor them into smaller functions for easier development and maintenance. Again, those would be improvement at the layer 1."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Layer 1: Modular actions\n",
    "\n",
    "In th next snippets, we refactor actions using Hamilton, a lightweight library to structure data transformations as directed acyclic graphs (DAGs). Hamilton uses the function and parameter names to infer the dependencies between functions and the graph structure.\n",
    "\n",
    "The next cell reimplements the `ingest_blog` action from `V2`. It uses `%%cell_to_module` from the Hamilton notebook extension to define a DAG in a single cell and view it ([see tutorial](https://github.com/DAGWorks-Inc/hamilton/blob/main/examples/jupyter_notebook_magic/example.ipynb))."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"1031pt\" height=\"318pt\"\n",
       " viewBox=\"0.00 0.00 1031.00 317.50\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 313.5)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-313.5 1027,-313.5 1027,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"26,-169.5 26,-301.5 122,-301.5 122,-169.5 26,-169.5\"/>\n",
       "<text text-anchor=\"middle\" x=\"74\" y=\"-286.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- overlapping_chunks -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>overlapping_chunks</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M845,-122.5C845,-122.5 692,-122.5 692,-122.5 686,-122.5 680,-116.5 680,-110.5 680,-110.5 680,-70.5 680,-70.5 680,-64.5 686,-58.5 692,-58.5 692,-58.5 845,-58.5 845,-58.5 851,-58.5 857,-64.5 857,-70.5 857,-70.5 857,-110.5 857,-110.5 857,-116.5 851,-122.5 845,-122.5\"/>\n",
       "<text text-anchor=\"start\" x=\"691\" y=\"-101.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">overlapping_chunks</text>\n",
       "<text text-anchor=\"start\" x=\"758\" y=\"-73.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">list</text>\n",
       "</g>\n",
       "<!-- embed_chunks -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>embed_chunks</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M1011,-158.5C1011,-158.5 898,-158.5 898,-158.5 892,-158.5 886,-152.5 886,-146.5 886,-146.5 886,-106.5 886,-106.5 886,-100.5 892,-94.5 898,-94.5 898,-94.5 1011,-94.5 1011,-94.5 1017,-94.5 1023,-100.5 1023,-106.5 1023,-106.5 1023,-146.5 1023,-146.5 1023,-152.5 1017,-158.5 1011,-158.5\"/>\n",
       "<text text-anchor=\"start\" x=\"897\" y=\"-137.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">embed_chunks</text>\n",
       "<text text-anchor=\"start\" x=\"941.5\" y=\"-109.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">dict</text>\n",
       "</g>\n",
       "<!-- overlapping_chunks&#45;&gt;embed_chunks -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>overlapping_chunks&#45;&gt;embed_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M857.19,-107.66C863.36,-108.86 869.55,-110.07 875.66,-111.27\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"875.35,-114.78 885.83,-113.26 876.69,-107.91 875.35,-114.78\"/>\n",
       "</g>\n",
       "<!-- parsed_text -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>parsed_text</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M435,-169.5C435,-169.5 343,-169.5 343,-169.5 337,-169.5 331,-163.5 331,-157.5 331,-157.5 331,-117.5 331,-117.5 331,-111.5 337,-105.5 343,-105.5 343,-105.5 435,-105.5 435,-105.5 441,-105.5 447,-111.5 447,-117.5 447,-117.5 447,-157.5 447,-157.5 447,-163.5 441,-169.5 435,-169.5\"/>\n",
       "<text text-anchor=\"start\" x=\"342\" y=\"-148.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">parsed_text</text>\n",
       "<text text-anchor=\"start\" x=\"379.5\" y=\"-120.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- sentences -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>sentences</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M603,-169.5C603,-169.5 524,-169.5 524,-169.5 518,-169.5 512,-163.5 512,-157.5 512,-157.5 512,-117.5 512,-117.5 512,-111.5 518,-105.5 524,-105.5 524,-105.5 603,-105.5 603,-105.5 609,-105.5 615,-111.5 615,-117.5 615,-117.5 615,-157.5 615,-157.5 615,-163.5 609,-169.5 603,-169.5\"/>\n",
       "<text text-anchor=\"start\" x=\"523\" y=\"-148.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">sentences</text>\n",
       "<text text-anchor=\"start\" x=\"553\" y=\"-120.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">list</text>\n",
       "</g>\n",
       "<!-- parsed_text&#45;&gt;sentences -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>parsed_text&#45;&gt;sentences</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M447.44,-137.5C464.89,-137.5 484.12,-137.5 501.78,-137.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"501.97,-141 511.97,-137.5 501.97,-134 501.97,-141\"/>\n",
       "</g>\n",
       "<!-- html_content -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>html_content</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M290,-169.5C290,-169.5 189,-169.5 189,-169.5 183,-169.5 177,-163.5 177,-157.5 177,-157.5 177,-117.5 177,-117.5 177,-111.5 183,-105.5 189,-105.5 189,-105.5 290,-105.5 290,-105.5 296,-105.5 302,-111.5 302,-117.5 302,-117.5 302,-157.5 302,-157.5 302,-163.5 296,-169.5 290,-169.5\"/>\n",
       "<text text-anchor=\"start\" x=\"188\" y=\"-148.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">html_content</text>\n",
       "<text text-anchor=\"start\" x=\"230\" y=\"-120.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- html_content&#45;&gt;parsed_text -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>html_content&#45;&gt;parsed_text</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M302.2,-137.5C308.27,-137.5 314.45,-137.5 320.57,-137.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"320.79,-141 330.79,-137.5 320.79,-134 320.79,-141\"/>\n",
       "</g>\n",
       "<!-- sentences&#45;&gt;overlapping_chunks -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>sentences&#45;&gt;overlapping_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M615.2,-125.76C631.9,-121.89 651.08,-117.46 670.06,-113.06\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"671,-116.43 679.95,-110.77 669.42,-109.62 671,-116.43\"/>\n",
       "</g>\n",
       "<!-- _overlapping_chunks_inputs -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>_overlapping_chunks_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"651,-87 476,-87 476,0 651,0 651,-87\"/>\n",
       "<text text-anchor=\"start\" x=\"525\" y=\"-60.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">window</text>\n",
       "<text text-anchor=\"start\" x=\"617.5\" y=\"-60.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">int</text>\n",
       "<text text-anchor=\"start\" x=\"531.5\" y=\"-39.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">stride</text>\n",
       "<text text-anchor=\"start\" x=\"617.5\" y=\"-39.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">int</text>\n",
       "<text text-anchor=\"start\" x=\"491.5\" y=\"-18.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">min_window_size</text>\n",
       "<text text-anchor=\"start\" x=\"617.5\" y=\"-18.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">int</text>\n",
       "</g>\n",
       "<!-- _overlapping_chunks_inputs&#45;&gt;overlapping_chunks -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>_overlapping_chunks_inputs&#45;&gt;overlapping_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M651.18,-63.57C657.4,-65.01 663.7,-66.47 669.98,-67.92\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"669.29,-71.35 679.82,-70.2 670.86,-64.53 669.29,-71.35\"/>\n",
       "</g>\n",
       "<!-- _html_content_inputs -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>_html_content_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"148,-160 0,-160 0,-115 148,-115 148,-160\"/>\n",
       "<text text-anchor=\"start\" x=\"15\" y=\"-133.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">blog_post_url</text>\n",
       "<text text-anchor=\"start\" x=\"114\" y=\"-133.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _html_content_inputs&#45;&gt;html_content -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>_html_content_inputs&#45;&gt;html_content</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M148.14,-137.5C154.24,-137.5 160.41,-137.5 166.5,-137.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"166.66,-141 176.66,-137.5 166.66,-134 166.66,-141\"/>\n",
       "</g>\n",
       "<!-- _embed_chunks_inputs -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>_embed_chunks_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"842.5,-186 694.5,-186 694.5,-141 842.5,-141 842.5,-186\"/>\n",
       "<text text-anchor=\"start\" x=\"709.5\" y=\"-159.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">blog_post_url</text>\n",
       "<text text-anchor=\"start\" x=\"808.5\" y=\"-159.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _embed_chunks_inputs&#45;&gt;embed_chunks -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>_embed_chunks_inputs&#45;&gt;embed_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M842.75,-148.77C853.65,-146.58 864.91,-144.31 875.89,-142.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"876.76,-145.5 885.88,-140.1 875.38,-138.64 876.76,-145.5\"/>\n",
       "</g>\n",
       "<!-- input -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>input</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"103.5,-270 44.5,-270 44.5,-233 103.5,-233 103.5,-270\"/>\n",
       "<text text-anchor=\"middle\" x=\"74\" y=\"-247.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M102,-215C102,-215 46,-215 46,-215 40,-215 34,-209 34,-203 34,-203 34,-190 34,-190 34,-184 40,-178 46,-178 46,-178 102,-178 102,-178 108,-178 114,-184 114,-190 114,-190 114,-203 114,-203 114,-209 108,-215 102,-215\"/>\n",
       "<text text-anchor=\"middle\" x=\"74\" y=\"-192.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x7f3a1754c390>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%cell_to_module ingest_blog --display\n",
    "import re\n",
    "import requests\n",
    "import lancedb\n",
    "from bs4 import BeautifulSoup\n",
    "from lancedb.pydantic import LanceModel, Vector\n",
    "from lancedb.embeddings import get_registry\n",
    "\n",
    "\n",
    "embedding_model = get_registry().get(\"openai\").create()\n",
    "\n",
    "class TextDocument(LanceModel):\n",
    "    \"\"\"Simple data structure to hold a piece of text associated with a url.\"\"\"\n",
    "    url: str\n",
    "    position: int\n",
    "    text: str = embedding_model.SourceField()\n",
    "    vector: Vector(dim=embedding_model.ndims()) = embedding_model.VectorField()\n",
    "\n",
    "\n",
    "def html_content(blog_post_url: str) -> str:\n",
    "    return requests.get(blog_post_url).text\n",
    "\n",
    "\n",
    "def parsed_text(html_content: str) -> str:\n",
    "    soup = BeautifulSoup(html_content, \"html.parser\")\n",
    "    return soup.get_text(separator=\" \", strip=True)\n",
    "    \n",
    "\n",
    "def sentences(parsed_text: str) -> list[str]:\n",
    "    return [\n",
    "        sentence.strip()\n",
    "        for sentence in re.split(r\"[.!?]+\", parsed_text)\n",
    "        if sentence.strip()\n",
    "    ]\n",
    "\n",
    "\n",
    "def overlapping_chunks(\n",
    "    sentences: list[str],\n",
    "    window: int = 5,\n",
    "    stride: int = 3,\n",
    "    min_window_size: int = 2\n",
    ") -> list[str]:\n",
    "    overlapping_chunks = []\n",
    "    n_chunks = len(sentences)\n",
    "    for start_i in range(0, n_chunks, stride):\n",
    "        if (start_i + window <= n_chunks) or (n_chunks - start_i >= min_window_size):\n",
    "            overlapping_chunks.append(\" \".join(sentences[start_i : min(start_i + window, n_chunks)]))\n",
    "    return overlapping_chunks\n",
    "\n",
    "\n",
    "def embed_chunks(overlapping_chunks: list[str], blog_post_url: str) -> dict:\n",
    "    # embed and store the chunks using LanceDB\n",
    "    con = lancedb.connect(\"./blogs\")\n",
    "    table = con.create_table(\"chunks\", exist_ok=True, schema=TextDocument)\n",
    "    table.add([\n",
    "        {\"text\": c, \"url\": blog_post_url, \"position\": i}\n",
    "        for i, c in enumerate(overlapping_chunks)\n",
    "    ])\n",
    "    return {\"n_chunks_embedded\": len(overlapping_chunks)}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "While this may seem trivial, these simple functions are easier to test, debug, and modify. It also allows us to develop and test actions outside of Burr. Hamilton has a great caching feature that can speed up development significantly when iterating over your application.\n",
    "\n",
    "Here, we create a `Driver` from the `ingest_blog` module we defined and enable caching."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from hamilton.driver import Builder\n",
    "\n",
    "ingest_dr = Builder().with_modules(ingest_blog).with_cache().build()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then, we request the `sentences` node to inspect results. This way, the `embed_chunks` node won't be executed and we won't spend time/credits on computing embeddings during development"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "We evaluated and completed proof-of-concepts with the top five commercial and open-source providers in the market\n"
     ]
    }
   ],
   "source": [
    "results = ingest_dr.execute(\n",
    "    [\"sentences\"],\n",
    "    inputs={\"blog_post_url\": \"https://blog.dagworks.io/p/building-a-better-feature-platform\"},\n",
    ")\n",
    "print(results[\"sentences\"][17])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we implement the `ask_question` action with Hamilton.\n",
    "\n",
    "We encourage considering prompt as code, which allows us to commit and version our prompt with the rest of our code. For instance, the function `system_prompt()` helps understand what information goes into the prompt and an additional docstring can add context to it ([related blog](https://blog.dagworks.io/p/llmops-production-prompt-engineering))."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"632pt\" height=\"212pt\"\n",
       " viewBox=\"0.00 0.00 632.00 212.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 208)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-208 628,-208 628,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"19,-64 19,-196 115,-196 115,-64 19,-64\"/>\n",
       "<text text-anchor=\"middle\" x=\"67\" y=\"-180.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- system_prompt -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>system_prompt</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M473,-64C473,-64 354,-64 354,-64 348,-64 342,-58 342,-52 342,-52 342,-12 342,-12 342,-6 348,0 354,0 354,0 473,0 473,0 479,0 485,-6 485,-12 485,-12 485,-52 485,-52 485,-58 479,-64 473,-64\"/>\n",
       "<text text-anchor=\"start\" x=\"353\" y=\"-42.8\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">system_prompt</text>\n",
       "<text text-anchor=\"start\" x=\"404\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- llm_answer -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>llm_answer</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M612,-100C612,-100 526,-100 526,-100 520,-100 514,-94 514,-88 514,-88 514,-48 514,-48 514,-42 520,-36 526,-36 526,-36 612,-36 612,-36 618,-36 624,-42 624,-48 624,-48 624,-88 624,-88 624,-94 618,-100 612,-100\"/>\n",
       "<text text-anchor=\"start\" x=\"525\" y=\"-78.8\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">llm_answer</text>\n",
       "<text text-anchor=\"start\" x=\"559.5\" y=\"-50.8\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- system_prompt&#45;&gt;llm_answer -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>system_prompt&#45;&gt;llm_answer</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M485.41,-48.63C491.55,-50.07 497.74,-51.52 503.82,-52.95\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"503.39,-56.44 513.92,-55.32 504.99,-49.63 503.39,-56.44\"/>\n",
       "</g>\n",
       "<!-- relevant_chunks -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>relevant_chunks</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M301,-64C301,-64 175,-64 175,-64 169,-64 163,-58 163,-52 163,-52 163,-12 163,-12 163,-6 169,0 175,0 175,0 301,0 301,0 307,0 313,-6 313,-12 313,-12 313,-52 313,-52 313,-58 307,-64 301,-64\"/>\n",
       "<text text-anchor=\"start\" x=\"174\" y=\"-42.8\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">relevant_chunks</text>\n",
       "<text text-anchor=\"start\" x=\"227.5\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">list</text>\n",
       "</g>\n",
       "<!-- relevant_chunks&#45;&gt;system_prompt -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>relevant_chunks&#45;&gt;system_prompt</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M313.08,-32C319.22,-32 325.44,-32 331.62,-32\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"331.97,-35.5 341.97,-32 331.97,-28.5 331.97,-35.5\"/>\n",
       "</g>\n",
       "<!-- _llm_answer_inputs -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>_llm_answer_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"480.5,-127.5 346.5,-127.5 346.5,-82.5 480.5,-82.5 480.5,-127.5\"/>\n",
       "<text text-anchor=\"start\" x=\"361.5\" y=\"-100.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">user_query</text>\n",
       "<text text-anchor=\"start\" x=\"446.5\" y=\"-100.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _llm_answer_inputs&#45;&gt;llm_answer -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>_llm_answer_inputs&#45;&gt;llm_answer</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M480.93,-88.99C488.6,-87.14 496.4,-85.26 504.03,-83.42\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"505.03,-86.78 513.93,-81.03 503.39,-79.97 505.03,-86.78\"/>\n",
       "</g>\n",
       "<!-- _relevant_chunks_inputs -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>_relevant_chunks_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"134,-54.5 0,-54.5 0,-9.5 134,-9.5 134,-54.5\"/>\n",
       "<text text-anchor=\"start\" x=\"15\" y=\"-27.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">user_query</text>\n",
       "<text text-anchor=\"start\" x=\"100\" y=\"-27.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _relevant_chunks_inputs&#45;&gt;relevant_chunks -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>_relevant_chunks_inputs&#45;&gt;relevant_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M134.31,-32C140.29,-32 146.4,-32 152.51,-32\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"152.78,-35.5 162.78,-32 152.78,-28.5 152.78,-35.5\"/>\n",
       "</g>\n",
       "<!-- input -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>input</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"96.5,-164.5 37.5,-164.5 37.5,-127.5 96.5,-127.5 96.5,-164.5\"/>\n",
       "<text text-anchor=\"middle\" x=\"67\" y=\"-142.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M95,-109.5C95,-109.5 39,-109.5 39,-109.5 33,-109.5 27,-103.5 27,-97.5 27,-97.5 27,-84.5 27,-84.5 27,-78.5 33,-72.5 39,-72.5 39,-72.5 95,-72.5 95,-72.5 101,-72.5 107,-78.5 107,-84.5 107,-84.5 107,-97.5 107,-97.5 107,-103.5 101,-109.5 95,-109.5\"/>\n",
       "<text text-anchor=\"middle\" x=\"67\" y=\"-87.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<graphviz.graphs.Digraph at 0x7f3a14833350>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%cell_to_module ask_question --display\n",
    "import openai\n",
    "import lancedb\n",
    "\n",
    "def relevant_chunks(user_query: str) -> list[dict]:\n",
    "    chunks_table = lancedb.connect(\"./blogs\").open_table(\"chunks\")\n",
    "    search_results = (\n",
    "        chunks_table\n",
    "        .search(user_query)\n",
    "        .select([\"text\", \"url\", \"position\"])\n",
    "        .limit(3)\n",
    "        .to_list()\n",
    "    )\n",
    "    return search_results\n",
    "\n",
    "\n",
    "def system_prompt(relevant_chunks: list[dict]) -> str:\n",
    "    relevant_content = \"\\n\".join([c[\"text\"] for c in relevant_chunks])\n",
    "    return (\n",
    "        \"Answer the user's questions based on the provided blog post content. \"\n",
    "        \"Answer in a concise and helpful manner, and tell the user \"\n",
    "        \"if you don't know the answer or you're unsure.\\n\\n\"\n",
    "        f\"BLOG CONTENT:\\n{relevant_content}\"\n",
    "    )\n",
    "\n",
    "def llm_answer(system_prompt: str, user_query: str) -> str:\n",
    "    client = openai.OpenAI()\n",
    "    response = client.chat.completions.create(\n",
    "        model=\"gpt-4o-mini\",\n",
    "        messages=[\n",
    "            {\"role\": \"system\", \"content\": system_prompt},\n",
    "            {\"role\": \"user\", \"content\": user_query}\n",
    "        ],\n",
    "    )\n",
    "    return response.choices[0].message.content"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Layer 2: Using Hamilton with Burr\n",
    "\n",
    "Since Burr is not opinionated about the implementation of `@action` functions, you can simply call Hamilton from it. We add the `OpenTelemetryTracer` to the Hamilton `Driver` to get tracing in Burr UI.\n",
    "\n",
    "You'll see that the Layer 2 becomes much lighter and only the high-level logic remains."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "from hamilton.driver import Builder\n",
    "from hamilton.plugins.h_opentelemetry import OpenTelemetryTracer\n",
    "from burr.core import action, State, ApplicationBuilder\n",
    "\n",
    "# these imports will only work if you executed the cells that\n",
    "# defines them using the `%%cell_to_module` magic \n",
    "import ingest_blog\n",
    "import ask_question\n",
    "\n",
    "\n",
    "@action(reads=[], writes=[])\n",
    "def ingest_blog_v3(state: State, blog_post_url: str) -> State:\n",
    "    \"\"\"Download a blog post and parse it\"\"\"\n",
    "    dr = (\n",
    "        Builder()\n",
    "        .with_modules(ingest_blog)\n",
    "        .with_adapters(OpenTelemetryTracer())\n",
    "        .build()\n",
    "    )\n",
    "    dr.execute([\"embed_chunks\"], inputs={\"blog_post_url\": blog_post_url}) \n",
    "    return state\n",
    "\n",
    "\n",
    "@action(reads=[], writes=[\"llm_answer\"])\n",
    "def ask_question_v3(state: State, user_query: str) -> State:\n",
    "    \"\"\"Reply to the user's query using the blog's content.\"\"\"\n",
    "    dr = (\n",
    "        Builder()\n",
    "        .with_modules(ask_question)\n",
    "        .with_adapters(OpenTelemetryTracer())\n",
    "        .build()\n",
    "    )\n",
    "    results = dr.execute([\"llm_answer\"], inputs={\"user_query\": user_query}) \n",
    "    return state.update(llm_answer=results[\"llm_answer\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"303pt\" height=\"177pt\"\n",
       " viewBox=\"0.00 0.00 303.00 177.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 173)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-173 299,-173 299,4 -4,4\"/>\n",
       "<!-- ingest_blog -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>ingest_blog</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M254,-103C254,-103 176,-103 176,-103 170,-103 164,-97 164,-91 164,-91 164,-78 164,-78 164,-72 170,-66 176,-66 176,-66 254,-66 254,-66 260,-66 266,-72 266,-78 266,-78 266,-91 266,-91 266,-97 260,-103 254,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ingest_blog</text>\n",
       "</g>\n",
       "<!-- ask_question -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>ask_question</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M188.5,-37C188.5,-37 99.5,-37 99.5,-37 93.5,-37 87.5,-31 87.5,-25 87.5,-25 87.5,-12 87.5,-12 87.5,-6 93.5,0 99.5,0 99.5,0 188.5,0 188.5,0 194.5,0 200.5,-6 200.5,-12 200.5,-12 200.5,-25 200.5,-25 200.5,-31 194.5,-37 188.5,-37\"/>\n",
       "<text text-anchor=\"middle\" x=\"144\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ask_question</text>\n",
       "</g>\n",
       "<!-- ingest_blog&#45;&gt;ask_question -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>ingest_blog&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M195.22,-65.67C187.84,-59.01 179.31,-51.33 171.36,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"173.44,-41.33 163.67,-37.23 168.76,-46.53 173.44,-41.33\"/>\n",
       "</g>\n",
       "<!-- input__blog_post_url -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>input__blog_post_url</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"295,-169 135,-169 135,-132 295,-132 295,-169\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-146.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: blog_post_url</text>\n",
       "</g>\n",
       "<!-- input__blog_post_url&#45;&gt;ingest_blog -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>input__blog_post_url&#45;&gt;ingest_blog</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M215,-131.67C215,-125.99 215,-119.55 215,-113.33\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"218.5,-113.23 215,-103.23 211.5,-113.23 218.5,-113.23\"/>\n",
       "</g>\n",
       "<!-- input__user_query -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>input__user_query</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"146,-103 0,-103 0,-66 146,-66 146,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"73\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: user_query</text>\n",
       "</g>\n",
       "<!-- input__user_query&#45;&gt;ask_question -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>input__user_query&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M92.78,-65.67C100.16,-59.01 108.69,-51.33 116.64,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"119.24,-46.53 124.33,-37.23 114.56,-41.33 119.24,-46.53\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<burr.core.application.Application at 0x7f3a1483f510>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app_v3 = (\n",
    "    ApplicationBuilder()\n",
    "    .with_actions(ingest_blog=ingest_blog_v3, ask_question=ask_question_v3)\n",
    "    .with_transitions((\"ingest_blog\", \"ask_question\"))\n",
    "    .with_entrypoint(\"ingest_blog\")\n",
    "    .with_tracker(project=\"modular-rag\", use_otel_tracing=True)\n",
    "    .build()\n",
    ")\n",
    "app_v3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "This is trying to return without having computed a single action -- we'll end up just returning some Nones. This means that nothing was executed (E.G. that the state machine had nowhere to go). Either fix the state machine orthe halt conditions, or both... Halt conditions are: halt_before=[], halt_after=['ask_question'].Note that this is considered undefined behavior -- if you get here, you should fix!\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "In a RAG application, you need to monitor the following aspects:\n",
      "\n",
      "1. **User Behavior Patterns**: This includes frequent topics and difficult queries that users engage with.\n",
      "2. **Application Performance**: You should track metrics such as guardrails, LLM randomness, and user ratings.\n",
      "3. **System Performance**: Monitor system metrics like latency, throughput, resource usage, and API calls.\n",
      "4. **System Errors**: Keep an eye on bugs that may arise from code or the interaction between code and data.\n"
     ]
    }
   ],
   "source": [
    "action_name, results, state = app_v2.run(\n",
    "    halt_after=[\"ask_question\"],\n",
    "    inputs={\n",
    "        \"blog_post_url\": \"https://blog.dagworks.io/p/from-blog-to-bot-build-a-rag-app\",\n",
    "        \"user_query\": \"What do you need to monitor in a RAG app?\"\n",
    "    }\n",
    ")\n",
    "print(state[\"llm_answer\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The biggest benefit of Burr + Hamilton is the unbeatable observability you get. The Burr UI will show a granular breakdown of the operations.\n",
    "\n",
    "![image.png](burr_ui_app_v3.png)\n",
    "\n",
    "Hamilton even has its dedicated [Hamilton UI](https://hamilton.dagworks.io/en/latest/hamilton-ui/ui/) that tracks execution, catalogs data transformations, and provides in-depth introspection. We're looking to integrate the two further together!\n",
    "\n",
    "![image.png](hamilton_ui.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Actually, two tricks can help simplify the code:\n",
    "- Build a single `Driver` from both action modules\n",
    "- Pass the `Driver` as an `@action` input using `.bind()` instead of building the `Driver` each time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"1083pt\" height=\"427pt\"\n",
       " viewBox=\"0.00 0.00 1083.00 426.50\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 422.5)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-422.5 1079,-422.5 1079,4 -4,4\"/>\n",
       "<g id=\"clust1\" class=\"cluster\">\n",
       "<title>cluster__legend</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" points=\"26,-278.5 26,-410.5 122,-410.5 122,-278.5 26,-278.5\"/>\n",
       "<text text-anchor=\"middle\" x=\"74\" y=\"-395.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">Legend</text>\n",
       "</g>\n",
       "<!-- llm_answer -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>llm_answer</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M658.5,-90.5C658.5,-90.5 572.5,-90.5 572.5,-90.5 566.5,-90.5 560.5,-84.5 560.5,-78.5 560.5,-78.5 560.5,-38.5 560.5,-38.5 560.5,-32.5 566.5,-26.5 572.5,-26.5 572.5,-26.5 658.5,-26.5 658.5,-26.5 664.5,-26.5 670.5,-32.5 670.5,-38.5 670.5,-38.5 670.5,-78.5 670.5,-78.5 670.5,-84.5 664.5,-90.5 658.5,-90.5\"/>\n",
       "<text text-anchor=\"start\" x=\"571.5\" y=\"-69.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">llm_answer</text>\n",
       "<text text-anchor=\"start\" x=\"606\" y=\"-41.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- overlapping_chunks -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>overlapping_chunks</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M897,-231.5C897,-231.5 744,-231.5 744,-231.5 738,-231.5 732,-225.5 732,-219.5 732,-219.5 732,-179.5 732,-179.5 732,-173.5 738,-167.5 744,-167.5 744,-167.5 897,-167.5 897,-167.5 903,-167.5 909,-173.5 909,-179.5 909,-179.5 909,-219.5 909,-219.5 909,-225.5 903,-231.5 897,-231.5\"/>\n",
       "<text text-anchor=\"start\" x=\"743\" y=\"-210.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">overlapping_chunks</text>\n",
       "<text text-anchor=\"start\" x=\"810\" y=\"-182.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">list</text>\n",
       "</g>\n",
       "<!-- embed_chunks -->\n",
       "<g id=\"node7\" class=\"node\">\n",
       "<title>embed_chunks</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M1063,-267.5C1063,-267.5 950,-267.5 950,-267.5 944,-267.5 938,-261.5 938,-255.5 938,-255.5 938,-215.5 938,-215.5 938,-209.5 944,-203.5 950,-203.5 950,-203.5 1063,-203.5 1063,-203.5 1069,-203.5 1075,-209.5 1075,-215.5 1075,-215.5 1075,-255.5 1075,-255.5 1075,-261.5 1069,-267.5 1063,-267.5\"/>\n",
       "<text text-anchor=\"start\" x=\"949\" y=\"-246.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">embed_chunks</text>\n",
       "<text text-anchor=\"start\" x=\"993.5\" y=\"-218.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">dict</text>\n",
       "</g>\n",
       "<!-- overlapping_chunks&#45;&gt;embed_chunks -->\n",
       "<g id=\"edge9\" class=\"edge\">\n",
       "<title>overlapping_chunks&#45;&gt;embed_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M909.19,-216.66C915.36,-217.86 921.55,-219.07 927.66,-220.27\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"927.35,-223.78 937.83,-222.26 928.69,-216.91 927.35,-223.78\"/>\n",
       "</g>\n",
       "<!-- parsed_text -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>parsed_text</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M473.5,-278.5C473.5,-278.5 381.5,-278.5 381.5,-278.5 375.5,-278.5 369.5,-272.5 369.5,-266.5 369.5,-266.5 369.5,-226.5 369.5,-226.5 369.5,-220.5 375.5,-214.5 381.5,-214.5 381.5,-214.5 473.5,-214.5 473.5,-214.5 479.5,-214.5 485.5,-220.5 485.5,-226.5 485.5,-226.5 485.5,-266.5 485.5,-266.5 485.5,-272.5 479.5,-278.5 473.5,-278.5\"/>\n",
       "<text text-anchor=\"start\" x=\"380.5\" y=\"-257.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">parsed_text</text>\n",
       "<text text-anchor=\"start\" x=\"418\" y=\"-229.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- sentences -->\n",
       "<g id=\"node5\" class=\"node\">\n",
       "<title>sentences</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M655,-278.5C655,-278.5 576,-278.5 576,-278.5 570,-278.5 564,-272.5 564,-266.5 564,-266.5 564,-226.5 564,-226.5 564,-220.5 570,-214.5 576,-214.5 576,-214.5 655,-214.5 655,-214.5 661,-214.5 667,-220.5 667,-226.5 667,-226.5 667,-266.5 667,-266.5 667,-272.5 661,-278.5 655,-278.5\"/>\n",
       "<text text-anchor=\"start\" x=\"575\" y=\"-257.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">sentences</text>\n",
       "<text text-anchor=\"start\" x=\"605\" y=\"-229.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">list</text>\n",
       "</g>\n",
       "<!-- parsed_text&#45;&gt;sentences -->\n",
       "<g id=\"edge7\" class=\"edge\">\n",
       "<title>parsed_text&#45;&gt;sentences</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M485.57,-246.5C507.14,-246.5 531.76,-246.5 553.67,-246.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"553.85,-250 563.85,-246.5 553.85,-243 553.85,-250\"/>\n",
       "</g>\n",
       "<!-- html_content -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>html_content</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M302.5,-278.5C302.5,-278.5 201.5,-278.5 201.5,-278.5 195.5,-278.5 189.5,-272.5 189.5,-266.5 189.5,-266.5 189.5,-226.5 189.5,-226.5 189.5,-220.5 195.5,-214.5 201.5,-214.5 201.5,-214.5 302.5,-214.5 302.5,-214.5 308.5,-214.5 314.5,-220.5 314.5,-226.5 314.5,-226.5 314.5,-266.5 314.5,-266.5 314.5,-272.5 308.5,-278.5 302.5,-278.5\"/>\n",
       "<text text-anchor=\"start\" x=\"200.5\" y=\"-257.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">html_content</text>\n",
       "<text text-anchor=\"start\" x=\"242.5\" y=\"-229.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- html_content&#45;&gt;parsed_text -->\n",
       "<g id=\"edge5\" class=\"edge\">\n",
       "<title>html_content&#45;&gt;parsed_text</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M314.66,-246.5C329.14,-246.5 344.64,-246.5 359.35,-246.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"359.39,-250 369.39,-246.5 359.39,-243 359.39,-250\"/>\n",
       "</g>\n",
       "<!-- sentences&#45;&gt;overlapping_chunks -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>sentences&#45;&gt;overlapping_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M667.2,-234.76C683.9,-230.89 703.08,-226.46 722.06,-222.06\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"723,-225.43 731.95,-219.77 721.42,-218.62 723,-225.43\"/>\n",
       "</g>\n",
       "<!-- system_prompt -->\n",
       "<g id=\"node6\" class=\"node\">\n",
       "<title>system_prompt</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M487,-127.5C487,-127.5 368,-127.5 368,-127.5 362,-127.5 356,-121.5 356,-115.5 356,-115.5 356,-75.5 356,-75.5 356,-69.5 362,-63.5 368,-63.5 368,-63.5 487,-63.5 487,-63.5 493,-63.5 499,-69.5 499,-75.5 499,-75.5 499,-115.5 499,-115.5 499,-121.5 493,-127.5 487,-127.5\"/>\n",
       "<text text-anchor=\"start\" x=\"367\" y=\"-106.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">system_prompt</text>\n",
       "<text text-anchor=\"start\" x=\"418\" y=\"-78.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- system_prompt&#45;&gt;llm_answer -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>system_prompt&#45;&gt;llm_answer</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M499.08,-81.46C515.93,-78.11 533.83,-74.55 550.37,-71.26\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"551.35,-74.63 560.48,-69.25 549.98,-67.77 551.35,-74.63\"/>\n",
       "</g>\n",
       "<!-- relevant_chunks -->\n",
       "<g id=\"node8\" class=\"node\">\n",
       "<title>relevant_chunks</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M315,-127.5C315,-127.5 189,-127.5 189,-127.5 183,-127.5 177,-121.5 177,-115.5 177,-115.5 177,-75.5 177,-75.5 177,-69.5 183,-63.5 189,-63.5 189,-63.5 315,-63.5 315,-63.5 321,-63.5 327,-69.5 327,-75.5 327,-75.5 327,-115.5 327,-115.5 327,-121.5 321,-127.5 315,-127.5\"/>\n",
       "<text text-anchor=\"start\" x=\"188\" y=\"-106.3\" font-family=\"Helvetica,sans-Serif\" font-weight=\"bold\" font-size=\"14.00\">relevant_chunks</text>\n",
       "<text text-anchor=\"start\" x=\"241.5\" y=\"-78.3\" font-family=\"Helvetica,sans-Serif\" font-style=\"italic\" font-size=\"14.00\">list</text>\n",
       "</g>\n",
       "<!-- relevant_chunks&#45;&gt;system_prompt -->\n",
       "<g id=\"edge8\" class=\"edge\">\n",
       "<title>relevant_chunks&#45;&gt;system_prompt</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M327.08,-95.5C333.22,-95.5 339.44,-95.5 345.62,-95.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"345.97,-99 355.97,-95.5 345.97,-92 345.97,-99\"/>\n",
       "</g>\n",
       "<!-- _llm_answer_inputs -->\n",
       "<g id=\"node9\" class=\"node\">\n",
       "<title>_llm_answer_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"494.5,-45 360.5,-45 360.5,0 494.5,0 494.5,-45\"/>\n",
       "<text text-anchor=\"start\" x=\"375.5\" y=\"-18.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">user_query</text>\n",
       "<text text-anchor=\"start\" x=\"460.5\" y=\"-18.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _llm_answer_inputs&#45;&gt;llm_answer -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>_llm_answer_inputs&#45;&gt;llm_answer</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M494.6,-35.29C512.75,-38.81 532.39,-42.61 550.43,-46.1\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"549.78,-49.54 560.26,-48 551.11,-42.67 549.78,-49.54\"/>\n",
       "</g>\n",
       "<!-- _overlapping_chunks_inputs -->\n",
       "<g id=\"node10\" class=\"node\">\n",
       "<title>_overlapping_chunks_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"703,-196 528,-196 528,-109 703,-109 703,-196\"/>\n",
       "<text text-anchor=\"start\" x=\"577\" y=\"-169.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">window</text>\n",
       "<text text-anchor=\"start\" x=\"669.5\" y=\"-169.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">int</text>\n",
       "<text text-anchor=\"start\" x=\"583.5\" y=\"-148.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">stride</text>\n",
       "<text text-anchor=\"start\" x=\"669.5\" y=\"-148.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">int</text>\n",
       "<text text-anchor=\"start\" x=\"543.5\" y=\"-127.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">min_window_size</text>\n",
       "<text text-anchor=\"start\" x=\"669.5\" y=\"-127.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">int</text>\n",
       "</g>\n",
       "<!-- _overlapping_chunks_inputs&#45;&gt;overlapping_chunks -->\n",
       "<g id=\"edge4\" class=\"edge\">\n",
       "<title>_overlapping_chunks_inputs&#45;&gt;overlapping_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M703.18,-172.57C709.4,-174.01 715.7,-175.47 721.98,-176.92\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"721.29,-180.35 731.82,-179.2 722.86,-173.53 721.29,-180.35\"/>\n",
       "</g>\n",
       "<!-- _html_content_inputs -->\n",
       "<g id=\"node11\" class=\"node\">\n",
       "<title>_html_content_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"148,-269 0,-269 0,-224 148,-224 148,-269\"/>\n",
       "<text text-anchor=\"start\" x=\"15\" y=\"-242.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">blog_post_url</text>\n",
       "<text text-anchor=\"start\" x=\"114\" y=\"-242.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _html_content_inputs&#45;&gt;html_content -->\n",
       "<g id=\"edge6\" class=\"edge\">\n",
       "<title>_html_content_inputs&#45;&gt;html_content</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M148.11,-246.5C158.38,-246.5 168.93,-246.5 179.18,-246.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"179.3,-250 189.3,-246.5 179.3,-243 179.3,-250\"/>\n",
       "</g>\n",
       "<!-- _embed_chunks_inputs -->\n",
       "<g id=\"node12\" class=\"node\">\n",
       "<title>_embed_chunks_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"894.5,-295 746.5,-295 746.5,-250 894.5,-250 894.5,-295\"/>\n",
       "<text text-anchor=\"start\" x=\"761.5\" y=\"-268.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">blog_post_url</text>\n",
       "<text text-anchor=\"start\" x=\"860.5\" y=\"-268.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _embed_chunks_inputs&#45;&gt;embed_chunks -->\n",
       "<g id=\"edge10\" class=\"edge\">\n",
       "<title>_embed_chunks_inputs&#45;&gt;embed_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M894.75,-257.77C905.65,-255.58 916.91,-253.31 927.89,-251.11\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"928.76,-254.5 937.88,-249.1 927.38,-247.64 928.76,-254.5\"/>\n",
       "</g>\n",
       "<!-- _relevant_chunks_inputs -->\n",
       "<g id=\"node13\" class=\"node\">\n",
       "<title>_relevant_chunks_inputs</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"141,-118 7,-118 7,-73 141,-73 141,-118\"/>\n",
       "<text text-anchor=\"start\" x=\"22\" y=\"-91.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">user_query</text>\n",
       "<text text-anchor=\"start\" x=\"107\" y=\"-91.3\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">str</text>\n",
       "</g>\n",
       "<!-- _relevant_chunks_inputs&#45;&gt;relevant_chunks -->\n",
       "<g id=\"edge11\" class=\"edge\">\n",
       "<title>_relevant_chunks_inputs&#45;&gt;relevant_chunks</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M141.04,-95.5C149.45,-95.5 158.15,-95.5 166.8,-95.5\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"166.91,-99 176.91,-95.5 166.91,-92 166.91,-99\"/>\n",
       "</g>\n",
       "<!-- input -->\n",
       "<g id=\"node14\" class=\"node\">\n",
       "<title>input</title>\n",
       "<polygon fill=\"#ffffff\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"103.5,-379 44.5,-379 44.5,-342 103.5,-342 103.5,-379\"/>\n",
       "<text text-anchor=\"middle\" x=\"74\" y=\"-356.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input</text>\n",
       "</g>\n",
       "<!-- function -->\n",
       "<g id=\"node15\" class=\"node\">\n",
       "<title>function</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M102,-324C102,-324 46,-324 46,-324 40,-324 34,-318 34,-312 34,-312 34,-299 34,-299 34,-293 40,-287 46,-287 46,-287 102,-287 102,-287 108,-287 114,-293 114,-299 114,-299 114,-312 114,-312 114,-318 108,-324 102,-324\"/>\n",
       "<text text-anchor=\"middle\" x=\"74\" y=\"-301.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">function</text>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<hamilton.driver.Driver at 0x7f3a1754d490>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dr = Builder().with_modules(ingest_blog, ask_question).with_adapters(OpenTelemetryTracer()).build()\n",
    "dr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<!-- Generated by graphviz version 2.43.0 (0)\n",
       " -->\n",
       "<!-- Title: %3 Pages: 1 -->\n",
       "<svg width=\"303pt\" height=\"177pt\"\n",
       " viewBox=\"0.00 0.00 303.00 177.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 173)\">\n",
       "<title>%3</title>\n",
       "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-173 299,-173 299,4 -4,4\"/>\n",
       "<!-- ingest_blog -->\n",
       "<g id=\"node1\" class=\"node\">\n",
       "<title>ingest_blog</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M254,-103C254,-103 176,-103 176,-103 170,-103 164,-97 164,-91 164,-91 164,-78 164,-78 164,-72 170,-66 176,-66 176,-66 254,-66 254,-66 260,-66 266,-72 266,-78 266,-78 266,-91 266,-91 266,-97 260,-103 254,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ingest_blog</text>\n",
       "</g>\n",
       "<!-- ask_question -->\n",
       "<g id=\"node3\" class=\"node\">\n",
       "<title>ask_question</title>\n",
       "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M188.5,-37C188.5,-37 99.5,-37 99.5,-37 93.5,-37 87.5,-31 87.5,-25 87.5,-25 87.5,-12 87.5,-12 87.5,-6 93.5,0 99.5,0 99.5,0 188.5,0 188.5,0 194.5,0 200.5,-6 200.5,-12 200.5,-12 200.5,-25 200.5,-25 200.5,-31 194.5,-37 188.5,-37\"/>\n",
       "<text text-anchor=\"middle\" x=\"144\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">ask_question</text>\n",
       "</g>\n",
       "<!-- ingest_blog&#45;&gt;ask_question -->\n",
       "<g id=\"edge3\" class=\"edge\">\n",
       "<title>ingest_blog&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M195.22,-65.67C187.84,-59.01 179.31,-51.33 171.36,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"173.44,-41.33 163.67,-37.23 168.76,-46.53 173.44,-41.33\"/>\n",
       "</g>\n",
       "<!-- input__blog_post_url -->\n",
       "<g id=\"node2\" class=\"node\">\n",
       "<title>input__blog_post_url</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"295,-169 135,-169 135,-132 295,-132 295,-169\"/>\n",
       "<text text-anchor=\"middle\" x=\"215\" y=\"-146.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: blog_post_url</text>\n",
       "</g>\n",
       "<!-- input__blog_post_url&#45;&gt;ingest_blog -->\n",
       "<g id=\"edge1\" class=\"edge\">\n",
       "<title>input__blog_post_url&#45;&gt;ingest_blog</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M215,-131.67C215,-125.99 215,-119.55 215,-113.33\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"218.5,-113.23 215,-103.23 211.5,-113.23 218.5,-113.23\"/>\n",
       "</g>\n",
       "<!-- input__user_query -->\n",
       "<g id=\"node4\" class=\"node\">\n",
       "<title>input__user_query</title>\n",
       "<polygon fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" points=\"146,-103 0,-103 0,-66 146,-66 146,-103\"/>\n",
       "<text text-anchor=\"middle\" x=\"73\" y=\"-80.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">input: user_query</text>\n",
       "</g>\n",
       "<!-- input__user_query&#45;&gt;ask_question -->\n",
       "<g id=\"edge2\" class=\"edge\">\n",
       "<title>input__user_query&#45;&gt;ask_question</title>\n",
       "<path fill=\"none\" stroke=\"black\" d=\"M92.78,-65.67C100.16,-59.01 108.69,-51.33 116.64,-44.17\"/>\n",
       "<polygon fill=\"black\" stroke=\"black\" points=\"119.24,-46.53 124.33,-37.23 114.56,-41.33 119.24,-46.53\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "<burr.core.application.Application at 0x7f3a14849910>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from hamilton.driver import Driver, Builder\n",
    "from burr.core import action, State, ApplicationBuilder\n",
    "\n",
    "\n",
    "@action(reads=[], writes=[])\n",
    "def ingest_blog_v3_2(state: State, blog_post_url: str, dr: Driver) -> State:\n",
    "    \"\"\"Download a blog post and parse it\"\"\"\n",
    "    dr.execute([\"embed_chunks\"], inputs={\"blog_post_url\": blog_post_url}) \n",
    "    return state\n",
    "\n",
    "\n",
    "@action(reads=[], writes=[\"llm_answer\"])\n",
    "def ask_question_v3_2(state: State, user_query: str, dr: Driver) -> State:\n",
    "    \"\"\"Reply to the user's query using the blog's content.\"\"\"\n",
    "    results = dr.execute([\"llm_answer\"], inputs={\"user_query\": user_query}) \n",
    "    return state.update(llm_answer=results[\"llm_answer\"])\n",
    "\n",
    "\n",
    "app_v3_2 = (\n",
    "    ApplicationBuilder()\n",
    "    .with_actions(\n",
    "        ingest_blog=ingest_blog_v3_2.bind(dr=dr),\n",
    "        ask_question=ask_question_v3_2.bind(dr=dr)\n",
    "    )\n",
    "    .with_transitions((\"ingest_blog\", \"ask_question\"))\n",
    "    .with_entrypoint(\"ingest_blog\")\n",
    "    .build()\n",
    ")\n",
    "app_v3_2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "We presented the 2-layer approach to building a RAG application, which separates the high-level logic from the implementation of individual actions.\n",
    "\n",
    "The key lesson is that you should adopt frameworks incrementally. A tool shouldn't lock you in and limit the evolution of your application. Adopting Burr from the start helps you develop in a principled way, and adding Hamilton as the complexity increases helps create a maintainable application.  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
